package com.stylefeng.guns.modular.apple.utils;

import cn.hutool.core.util.StrUtil;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSString;
import com.dd.plist.PropertyListFormatException;
import com.dd.plist.PropertyListParser;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.util.CmdUtil;
import jdk.nashorn.tools.Shell;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import xmlwise.Plist;
import xmlwise.XmlParseException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @program: guns-parent
 * @description:
 * @author: Mr. Stone
 * @create: 2020-06-23 14:30
 **/
public class AppUtil {

    private static final Logger logger = LoggerFactory.getLogger(AppUtil.class);

    public static void main(String[] args) {
        try {
            Map<String,Object> info = getInfoFromIpa("/var/data/DFPQIT/ios.ipa");
            System.out.println(info);
        } catch (IOException ee) {
            ee.printStackTrace();
        }
    }

    private static final int buffer = 2048;
    // 生成app目录，也是app_code
    public static String genericAppCode(Integer count) {
        char[] space = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
                'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
                'U', 'V', 'W', 'X', 'Y', 'Z'
        };
        char[] chs = new char[count];
        Random rom = new Random();
        for(int i = 0; i < count; i++) {
            char ch = space[rom.nextInt(36)];
            chs[i] = ch;
        }
        return String.valueOf(chs);
    }

    // 更新描述文件的url
    public static void updateMobileProfile(String profilePath ,
                                           String targetProfilePath,
                                           String url) throws IOException, XmlParseException {
        Map<String, Object> info = Plist.load(profilePath);
        Map<String, Object> content = (Map<String, Object>) info.get("PayloadContent");
        content.put("URL", url);
        info.put("PayloadContent", content);
        Plist.store(info, targetProfilePath);
    }

    public static void creatUDIDMobileconfig(String appName,
                                             String url,
                                             String targetPath,
                                             String rootPath) throws IOException {
        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +
                "<plist version=\"1.0\">\n" +
                "    <dict>\n" +
                "        <key>PayloadContent</key>\n" +
                "        <dict>\n" +
                "            <key>URL</key>\n" +
                "            <string>"+ url +"</string> <!--接收数据的接口地址-->\n" +
                "            <key>DeviceAttributes</key>\n" +
                "            <array>\n" +
                "                <string>SERIAL</string>\n" +
                "                <string>MAC_ADDRESS_EN0</string>\n" +
                "                <string>UDID</string>\n" +
                "                <string>IMEI</string>\n" +
                "                <string>ICCID</string>\n" +
                "                <string>VERSION</string>\n" +
                "                <string>PRODUCT</string>\n" +
                "            </array>\n" +
                "        </dict>\n" +
                "        <key>PayloadOrganization</key>\n" +
                "        <string>" + "Apple.Inc官方认证" +"</string>  <!--组织名称-->\n" +
                "        <key>PayloadDisplayName</key>\n" +
                "        <string>" + appName + "</string>  <!--安装时显示的标题-->\n" +
                "        <key>PayloadVersion</key>\n" +
                "        <integer>1</integer>\n" +
                "        <key>PayloadUUID</key>\n" +
                "        <string>"+ UUID.randomUUID().toString().replace("-", "") +"</string>  <!--自己随机填写的唯一字符串-->\n" +
                "        <key>PayloadIdentifier</key>\n" +
                "        <string>online.iizvv.profile-service</string>\n" +
                "        <key>PayloadDescription</key>\n" +
                "        <string>"+"该配置文件将帮助用户获取当前iOS设备的UDID号码"+"</string>   <!--描述-->\n" +
                "        <key>PayloadType</key>\n" +
                "        <string>Profile Service</string>\n" +
                "    </dict>\n" +
                "</plist>";
        String filePath =  targetPath + "/nosign.mobileconfig";
        System.out.println(xml);
        FileWriter writer = new FileWriter(filePath);
        writer.write(xml);
        writer.close();
        String serverKey = rootPath + "server.key";
        String ca = rootPath + "ca.cer";
        String serverCrt = rootPath + "server.cer";
        String filePath2 = targetPath + "/media.mobileconfig";
        String com = "openssl smime -sign -in " + filePath +" -out "+ filePath2 + " -signer "+serverCrt+" -inkey "+serverKey+"  -certfile "+ca+" -outform der -nodetach";
        System.out.println(com);
        CmdUtil.cmd(com);
    }

    public static Map<String, Object> getInfoFromIpa(String ipaPath) throws IOException {
        File file = unZip(ipaPath);
        Map<String, Object> info = new HashMap<>();
        NSDictionary dict = null;
        try {
            dict = (NSDictionary) PropertyListParser.parse(file);
            NSString versionStr = (NSString) dict.get("CFBundleShortVersionString");
            NSString bundleStr = (NSString) dict.get("CFBundleIdentifier");
            info.put("version", versionStr.toString());
            info.put("bundle", bundleStr.toString());
        } catch (ParserConfigurationException | SAXException | ParseException | PropertyListFormatException | IOException e) {
            throw new GunsException(BizExceptionEnum.INFO_PLIST_READ_ERROR);
        }finally {
            File ipaDir = new File(new File(ipaPath).getParent()
                    + File.separator + "ios" + File.separator);
            try {
                FileUtils.deleteDirectory(ipaDir);
            } catch (IOException e){
                e.printStackTrace();
                throw new GunsException(BizExceptionEnum.INFO_PLIST_READ_ERROR);
            } finally {
                logger.info("删除文件: {} 失败", ipaDir);
            }
        }
        return info;
    }

    public static File unZip(String ipaPath) throws IOException {
        int count = -1;
        File file = null;
        InputStream is = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        ZipFile zipFile = null;
        File result = null;

        String savepath = "";
        savepath = ipaPath.substring(0, ipaPath.lastIndexOf(".")) + File.separator;
        File existsSavePath = new File(savepath); // 创建保存目录
        if(existsSavePath.exists()){
            existsSavePath.delete();
        }
        existsSavePath.mkdir();

        zipFile = new ZipFile(ipaPath); // 解决中文乱码问题
        Enumeration<?> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            byte buf[] = new byte[buffer];
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String filename = entry.getName();
            boolean ismkdir = false;
            // 检查此文件是否带有文件夹
            if (filename.lastIndexOf("/") != -1) {
                ismkdir = true;
            }
            filename = savepath + filename;
            // 如果是文件夹先创建
            if (entry.isDirectory()) {
                file = new File(filename);
                file.mkdirs();
                continue;
            }
            file = new File(filename);
            // 如果是文件夹先创建
            if (!file.exists()) {
                if (ismkdir) {
                    new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs(); // 目录先创建
                }
            }
            file.createNewFile(); // 创建文件
            //判断文件名字
            if(filename.endsWith(".app/Info.plist")) {
                result = new File(filename);
            }

            is = zipFile.getInputStream(entry);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos, buffer);

            while ((count = is.read(buf)) > -1) {
                bos.write(buf, 0, count);
            }
            bos.flush();
            bos.close();
            fos.close();

            is.close();
        }
        zipFile.close();

        try {
            if (bos != null) {
                bos.close();
            }
            if (fos != null) {
                fos.close();
            }
            if (is != null) {
                is.close();
            }
            if (zipFile != null) {
                zipFile.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}
